/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.osiris.persistence.controllers.impl;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import org.osiris.persistence.Subtipo;
import org.osiris.persistence.Tiporecurso;
import org.osiris.persistence.Recurso;
import java.util.ArrayList;
import java.util.List;
import org.osiris.persistence.controllers.exceptions.IllegalOrphanException;
import org.osiris.persistence.controllers.exceptions.NonexistentEntityException;

/**
 *
 * @author amartinez
 */
public class SubtipoJpaController {

    public SubtipoJpaController() {
    	emf = CreadorPU.getEntityManagerFactory();
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Subtipo subtipo) {
        if (subtipo.getRecursoList() == null) {
            subtipo.setRecursoList(new ArrayList<Recurso>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Tiporecurso idTipoRecurso = subtipo.getIdTipoRecurso();
            if (idTipoRecurso != null) {
                idTipoRecurso = em.getReference(idTipoRecurso.getClass(), idTipoRecurso.getIdTipoRecurso());
                subtipo.setIdTipoRecurso(idTipoRecurso);
            }
            List<Recurso> attachedRecursoList = new ArrayList<Recurso>();
            for (Recurso recursoListRecursoToAttach : subtipo.getRecursoList()) {
                recursoListRecursoToAttach = em.getReference(recursoListRecursoToAttach.getClass(), recursoListRecursoToAttach.getIdRecurso());
                attachedRecursoList.add(recursoListRecursoToAttach);
            }
            subtipo.setRecursoList(attachedRecursoList);
            em.persist(subtipo);
            if (idTipoRecurso != null) {
                idTipoRecurso.getSubtipoList().add(subtipo);
                idTipoRecurso = em.merge(idTipoRecurso);
            }
            for (Recurso recursoListRecurso : subtipo.getRecursoList()) {
                Subtipo oldIdSubtipoOfRecursoListRecurso = recursoListRecurso.getIdSubtipo();
                recursoListRecurso.setIdSubtipo(subtipo);
                recursoListRecurso = em.merge(recursoListRecurso);
                if (oldIdSubtipoOfRecursoListRecurso != null) {
                    oldIdSubtipoOfRecursoListRecurso.getRecursoList().remove(recursoListRecurso);
                    oldIdSubtipoOfRecursoListRecurso = em.merge(oldIdSubtipoOfRecursoListRecurso);
                }
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Subtipo subtipo) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Subtipo persistentSubtipo = em.find(Subtipo.class, subtipo.getIdSubtipo());
            Tiporecurso idTipoRecursoOld = persistentSubtipo.getIdTipoRecurso();
            Tiporecurso idTipoRecursoNew = subtipo.getIdTipoRecurso();
            List<Recurso> recursoListOld = persistentSubtipo.getRecursoList();
            List<Recurso> recursoListNew = subtipo.getRecursoList();
            List<String> illegalOrphanMessages = null;
            for (Recurso recursoListOldRecurso : recursoListOld) {
                if (!recursoListNew.contains(recursoListOldRecurso)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Recurso " + recursoListOldRecurso + " since its idSubtipo field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (idTipoRecursoNew != null) {
                idTipoRecursoNew = em.getReference(idTipoRecursoNew.getClass(), idTipoRecursoNew.getIdTipoRecurso());
                subtipo.setIdTipoRecurso(idTipoRecursoNew);
            }
            List<Recurso> attachedRecursoListNew = new ArrayList<Recurso>();
            for (Recurso recursoListNewRecursoToAttach : recursoListNew) {
                recursoListNewRecursoToAttach = em.getReference(recursoListNewRecursoToAttach.getClass(), recursoListNewRecursoToAttach.getIdRecurso());
                attachedRecursoListNew.add(recursoListNewRecursoToAttach);
            }
            recursoListNew = attachedRecursoListNew;
            subtipo.setRecursoList(recursoListNew);
            subtipo = em.merge(subtipo);
            if (idTipoRecursoOld != null && !idTipoRecursoOld.equals(idTipoRecursoNew)) {
                idTipoRecursoOld.getSubtipoList().remove(subtipo);
                idTipoRecursoOld = em.merge(idTipoRecursoOld);
            }
            if (idTipoRecursoNew != null && !idTipoRecursoNew.equals(idTipoRecursoOld)) {
                idTipoRecursoNew.getSubtipoList().add(subtipo);
                idTipoRecursoNew = em.merge(idTipoRecursoNew);
            }
            for (Recurso recursoListNewRecurso : recursoListNew) {
                if (!recursoListOld.contains(recursoListNewRecurso)) {
                    Subtipo oldIdSubtipoOfRecursoListNewRecurso = recursoListNewRecurso.getIdSubtipo();
                    recursoListNewRecurso.setIdSubtipo(subtipo);
                    recursoListNewRecurso = em.merge(recursoListNewRecurso);
                    if (oldIdSubtipoOfRecursoListNewRecurso != null && !oldIdSubtipoOfRecursoListNewRecurso.equals(subtipo)) {
                        oldIdSubtipoOfRecursoListNewRecurso.getRecursoList().remove(recursoListNewRecurso);
                        oldIdSubtipoOfRecursoListNewRecurso = em.merge(oldIdSubtipoOfRecursoListNewRecurso);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Long id = subtipo.getIdSubtipo();
                if (findSubtipo(id) == null) {
                    throw new NonexistentEntityException("The subtipo with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Long id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Subtipo subtipo;
            try {
                subtipo = em.getReference(Subtipo.class, id);
                subtipo.getIdSubtipo();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The subtipo with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<Recurso> recursoListOrphanCheck = subtipo.getRecursoList();
            for (Recurso recursoListOrphanCheckRecurso : recursoListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Subtipo (" + subtipo + ") cannot be destroyed since the Recurso " + recursoListOrphanCheckRecurso + " in its recursoList field has a non-nullable idSubtipo field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Tiporecurso idTipoRecurso = subtipo.getIdTipoRecurso();
            if (idTipoRecurso != null) {
                idTipoRecurso.getSubtipoList().remove(subtipo);
                idTipoRecurso = em.merge(idTipoRecurso);
            }
            em.remove(subtipo);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Subtipo> findSubtipoEntities() {
        return findSubtipoEntities(true, -1, -1);
    }

    public List<Subtipo> findSubtipoEntities(int maxResults, int firstResult) {
        return findSubtipoEntities(false, maxResults, firstResult);
    }

    private List<Subtipo> findSubtipoEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Subtipo as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Subtipo findSubtipo(Long id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Subtipo.class, id);
        } finally {
            em.close();
        }
    }

    public int getSubtipoCount() {
        EntityManager em = getEntityManager();
        try {
            return ((Long) em.createQuery("select count(o) from Subtipo as o").getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

}
